package algorithm;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import util.VectorMath;

import algorithm.quartile.Distance;
import algorithm.quartile.DistanceTable_Centroid;
import algorithm.quartile.Distance_Centroid;

public class DistanceTable_Original extends DistanceTable_Centroid{

	private double mean;
	private double standardDeviation;

	public DistanceTable_Original(RADDACL_Cluster parent,
			Region region) {
		super(parent, region);
	}
	
	/**
	 * This method does nothing
	 */
	public double getThreshold()
	{
		return 0.0;
	}
	/**
	 * Returns the mean distance to the Centroid of this Distance Table
	 * 
	 * @return
	 */
	public double getMean()
	{
		return this.mean;
	}
	/**
	 * Returns the median distance from the Centroid of this Distance Table.
	 * 
	 * @return
	 */
	public double getMedian()
	{
		return this.distances.size() > 0 
				? this.distances.get(this.distances.size()/2).getDistance() 
				: 0.0;
	}
	/**
	 * Returns the Standard Deviation distance from the Centroid of this Distance Table
	 * 
	 * @return
	 */
	public double getStandardDeviation()
	{
		return this.standardDeviation;
	}

	/**
	 * Calculates the Mean Distance the points fall from the Centroid of a
	 * Region, and establishes the distance table on the fly.
	 * 
	 */
	protected void calculateMeanDistFromCentroid(RADDACL_Cluster parent) 
	{
		for (Integer i : this.region.getIndexes()) 
		{
			
			double distance = VectorMath.euclidianDistance(((Region_Original)this.region).getPCentroid(),
					parent.getInput().get(i));
			
			this.distances.add(new Distance_Centroid(i, distance));
			
			this.mean += distance;
		}

		this.mean = this.mean / ((double) this.region.getIndexes().size());
	}
	
	/**
	 * Calculates the Standard Deviation of this Region of inputs. Assumes
	 * the mean has already been calculated.
	 */
	protected void calculateStandardDeviation(RADDACL_Cluster parent) 
	{
		for(Distance distance: this.distances)
		{
			this.standardDeviation += distance.getDistance() - mean;
		}

		this.standardDeviation = StrictMath.sqrt(
				this.standardDeviation / ((double) distances.size()-1)
				);
	}
	
	@Override
	public void generateDistanceTable() {
		
		calculateCentroid(parent);
		
		if(((Region_Original)this.region).getPCentroid() != null)
		{
			
			this.calculateMeanDistFromCentroid(parent);
			this.calculateStandardDeviation(parent);
		
			Collections.sort(this.distances);	//sort the distances, so we can get the median easy
		}
	}
	
	
}
